﻿using WebApp.BLL.Manage;
using WebApp.Common.Caching;
using WebApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using WebApp.ViewModels.Manage;

namespace WebApp.Web.Core.Auth
{
    /// <summary>
    /// 权限拦截
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class AuthorizeFilterAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// {0}:用户Id
        /// {1}:权限编号
        /// </summary>
        private const string USER_AUTHORIZE_KEY = "WebApp.UserAuthorize.All.{0}-{1}";
        /// <summary>
        /// 缓存KEY（用于清除缓存）
        /// </summary>
        public const string USER_AUTHORIZE_ALLKEY = "WebApp.UserAuthorize.All.";

        public List<string> AuthCodeList { get; set; }
        public ActionType ActionType { get; set; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="authcode">权限编号</param>
        /// <param name="isMasterPage">是否主框架页</param>
        public AuthorizeFilterAttribute(string authcode, ActionType actionType = ActionType.MasterPage)
        {
            AuthCodeList = new List<string>();
            string[] ss = authcode.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            AuthCodeList.AddRange(ss);
            ActionType = actionType;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="authcode">权限编号</param>
        /// <param name="isMasterPage">是否主框架页</param>
        public AuthorizeFilterAttribute(string[] authcodes, ActionType actionType = ActionType.MasterPage)
        {
            AuthCodeList = new List<string>();
            AuthCodeList.AddRange(authcodes);
            ActionType = actionType;
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //if (filterContext == null)
            //{
            //    throw new ArgumentNullException("filterContext");
            //}
            if (AuthCodeList.Count == 0) throw new ArgumentNullException("authcode");

            var result = AuthorizeResult.NoAuthorized;

            foreach (string authcode in AuthCodeList)
            {
                result = AuthorizeCore(authcode);

                if (result == AuthorizeResult.Success) break;
                if (result == AuthorizeResult.NotLogin) break;
            }

            #region 未授权|未登录
            switch (result)
            {
                case AuthorizeResult.NoAuthorized:

                    //主框架页跳转到登录页
                    if (ActionType == ActionType.MasterPage)
                    {
                        filterContext.Result = new HttpUnauthorizedResult();
                    }
                    //弹出页显示重新登录
                    else if (ActionType == ActionType.PopupPage)
                    {
                        //note by qiulc:web.config里有<authentication mode="Forms">配置，所以如果返回HttpUnauthorizedResult，会直接跳转到登录页
                        //所以这里用自定义的状态码返回
                        filterContext.Result = new HttpStatusCodeResult((int)AuthHttpStatus.NotAuthorized);
                    }
                    //ajax处理，返回未经授权
                    else if (ActionType == ActionType.Ajax)
                    {
                        filterContext.Result = new HttpStatusCodeResult((int)AuthHttpStatus.NotAuthorized);
                    }

                    return;
                case AuthorizeResult.NotLogin:
                    //主框架页跳转到登录页
                    if (ActionType == ActionType.MasterPage)
                    {
                        var backurl = "";
                        if (filterContext.HttpContext != null
                            && filterContext.HttpContext.Request != null)
                        {
                            backurl = filterContext.HttpContext.Request.RawUrl;
                        }

                        filterContext.Result = new RedirectResult("~/Member/Login?backurl=" + System.Web.HttpUtility.UrlEncode(backurl));
                        //这时候还没有RouteTable，所以不能用这个
                        //filterContext.Result = new RedirectResult(UrlHelper.GenerateUrl("Default","Login", "Member",
                        //    new System.Web.Routing.RouteValueDictionary(),
                        //    new System.Web.Routing.RouteCollection(), 
                        //    filterContext.RequestContext, false));
                    }
                    //弹出页显示重新登录
                    else if (ActionType == ActionType.PopupPage)
                    {
                        filterContext.Result = new HttpStatusCodeResult((int)AuthHttpStatus.NotLogin);
                    }
                    //ajax处理，返回未经授权
                    else if (ActionType == ActionType.Ajax)
                    {
                        filterContext.Result = new HttpUnauthorizedResult();
                    }
                    return;
            }
            #endregion
        }

        /// <summary>
        /// 权限判断业务逻辑
        /// </summary>
        /// <param name="filterContext"></param>
        /// <returns></returns>
        /// <remarks>
        /// 1，是否已登录（会话超时）
        /// 2，是否有操作权限
        /// </remarks>
        internal static AuthorizeResult AuthorizeCore(string authcode)
        {
            //s_user suser = (s_user)filterContext.HttpContext.Session[S_userService.Session_USER_KEY];
            SessionUserModel suser = SessionManage.User;
            //判定用户是否登录
            if (suser == null)
            {
                return AuthorizeResult.NotLogin;
            }
            string key = string.Format(USER_AUTHORIZE_KEY, suser.Id, authcode);

            bool hasAuth = UserCache.GetUserAuths(suser).Count(x => x.Authcode == authcode) > 0;

            //bool hasAuth = new MemoryCacheManager().Get<bool>(key, () => {
            //    IList<Auth> userAuths = new S_userService().GetUserAuths(suser);

            //    return userAuths.Count(x => x.Authcode == authcode) > 0;
            //});

            if (hasAuth) return AuthorizeResult.Success;

            return AuthorizeResult.NoAuthorized;
        }
    }

    internal enum AuthorizeResult : int
    {
        /// <summary>
        /// 未登录
        /// </summary>
        NotLogin,
        /// <summary>
        /// 未授权
        /// </summary>
        NoAuthorized,
        Success
    }
    public enum AuthHttpStatus : int
    {
        /// <summary>
        /// 未授权
        /// </summary>
        NotAuthorized = 498,
        /// <summary>
        /// 未登录
        /// </summary>
        NotLogin = 499
    }
    public enum ActionType
    {
        MasterPage,
        PopupPage,
        Ajax
    }
}
